//
// @Author: zhengqi Wu
// @Description:
// @Version: 1.0.0
// @Date: 2021/3/3 19:00
// @Copyright: MIN-Group；国家重大科技基础设施——未来网络北大实验室；深圳市信息论与未来网络重点实验室
//

//
// 表示一个通用的 Nack
//
// @Description:
//  Nack 是一个特殊的兴趣包，其就是 Interest 中设置了 NackHeader
//	1. 包格式如下：
//		Nack = 5 TLV-LENGTH
//             { InterestIdentifier }        => 标识区
//             { Signature }                 => 签名区
//             {                             => 只读区
//				   [NackHeader]
//				   ...
//             }
//             {                             => 可变区
//				   ...
//             }
//

const {createInterestByMINPacket} = require("./Interest");
const {Interest} = require('./Interest')
class Nack{
    constructor() {
        this.Interest = new Interest()
    }

    //
    // 设置 Nack 的原因
    //
    // @Description:
    // @see component.NackReasonUnknown component.NackReasonDuplicate component.NackReasonNoRoute
    // @receiver n
    // @param reason
    //
    setNackReason(reason){
        this.Interest.NackHeader.setNackReason(reason)
    }

    //
    // 获取 Nack 的原因
    //
    // @Description:
    // @receiver n
    // @return uint64
    //
    getNackReason(){
        return this.Interest.NackHeader.getNackReason()
    }

    //
    // 将 Nack 线速编码为一个 TLV
    //
    // @Description:
    // @receiver n
    // @param encoder
    // @return int
    // @return error
    //
    wireEncode(enc) {
        try {
            if (this.Interest === undefined) {
                throw new NackError()
            }
            return this.Interest.wireEncode(enc)
        } catch (e) {
            throw e
        }
    }
    //
    // 从 TLV Block 中解码出一个 Nack
    //
    // @Description:
    // @receiver n
    // @param block
    // @return error
    //
    wireDecode(block) {
        try {
            if (this.Interest === undefined) {
                throw new NackError()
            }
            this.Interest.wireDecode(block)

        } catch (e) {
            throw e
        }
    }
}

class NackError extends Error {
    constructor(m) {
        super(m)
        this.name = 'MINPacketError'
    }

    error() {
        console.log(`${this.name}: ${this.message}`)
    }
}

function createNackByInterest(interest) {
    try {
        if (!interest.NackHeader.isInitial()) {
            throw new NackError()
        }
        let nack = new Nack()
        nack.Interest = interest
        nack.setNackReason(interest.NackHeader.getNackReason())
        return nack
    } catch (e) {
        throw e
    }
    
}

function createNackByMINPacket(minPacket) {
    let interest = createInterestByMINPacket(minPacket)
    return createNackByInterest(interest)
}

module.exports = {
    Nack: Nack,
    createNackByInterest: createNackByInterest,
    createNackByMINPacket: createNackByMINPacket
}